package cn.lg.soar.common.util;

import cn.lg.soar.common.util.data.StringUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;

/**
 * 验证器
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface Validator {

    /**
     * 正则校验
     * @return
     */
    static boolean matches(String regex, String string){
        if(string == null){
            return false;
        }
        return Pattern.compile(regex).matcher(string).matches();
    }

    /**
     * 字符是否中文
     * @param c
     * @return
     */
    static boolean isChinese(char c) {
        return c >= 0x4E00 && c <= 0x9FA5;
    }

    /**
     * 字符是否中文
     * @param s
     * @return
     */
    static boolean isChinese(String s) {
        if(s == null){
            return false;
        }
        char[] chars = s.toCharArray();
        for(char c : chars){
            if(!isChinese(c)){
                return false;
            }
        }
        return true;
    }
    String CHINESE_MSG = "必须是中文";

    /**
     * 邮箱验证
     * @param email
     * @return
     */
    static boolean isEmail(String email) {
        if(StringUtil.isBlank(email)){
            return false;
        }
        return EMAIL_PATTERN.matcher(email).matches();
    }
    String EMAIL_MSG = "邮箱不正确";
    String EMAIL_REGEXP = "^\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}$";
    Pattern EMAIL_PATTERN = Pattern.compile(EMAIL_REGEXP);

    /**
     * 手机号码验证
     * @param number
     * @return
     */
    static boolean isMobilePhone(String number) {
        if(StringUtil.isBlank(number)){
            return false;
        }
        return MOBILE_PATTERN.matcher(number).matches();
    }
    String MOBILE_MSG = "手机号不正确";
    String MOBILE_REGEXP = "^1[3-9]\\d{9}$";
    Pattern MOBILE_PATTERN = Pattern.compile(MOBILE_REGEXP);

    /**
     * 固定电话验证
     * @param number
     * @return
     */
    static boolean isFixedPhone(String number) {
        if(StringUtil.isBlank(number)){
            return false;
        }
        return FIXED_PHONE_PATTERN.matcher(number).matches();
    }
    String FIXED_MSG = "固定电话不正确";
    String FIXED_REGEXP = "^[0-9-()（）]{7,18}$";
    Pattern FIXED_PHONE_PATTERN = Pattern.compile(FIXED_REGEXP);

    /**
     * 联系电话（手机或固话）
     * @param number
     * @return
     */
    static boolean isContactPhone(String number) {
        if(StringUtil.isBlank(number)){
            return false;
        }
        return isMobilePhone(number) || isFixedPhone(number);
    }
    String CONTACT_PHONE_MSG = "联系电话";


    /**
     * 腾讯QQ号验证
     * @param number
     * @return
     */
    static boolean isQQ(String number) {
        if(StringUtil.isBlank(number)){
            return false;
        }
        return QQ_PATTERN.matcher(number).matches();
    }
    String QQ_MSG = "腾讯QQ号不正确";
    String QQ_REGEXP = "^[1-9]([0-9]{5,11})$";
    Pattern QQ_PATTERN = Pattern.compile(QQ_REGEXP);

    /**
     * 邮政编码验证
     * @param postcode
     * @return
     */
    static boolean isPostcode(String postcode) {
        if(StringUtil.isBlank(postcode)){
            return false;
        }
        return POSTCODE_PATTERN.matcher(postcode).matches();
    }
    String POSTCODE_MSG = "邮政编码不正确";
    String POSTCODE_REGEXP = "^\\d{6}$";
    Pattern POSTCODE_PATTERN = Pattern.compile(POSTCODE_REGEXP);

    /**
     * IP地址验证
     * @param ip
     * @return
     */
    static boolean isIP6(String ip) {
        if(StringUtil.isBlank(ip)){
            return false;
        }
        return IP6_PATTERN.matcher(ip).matches();
    }
    String IP6_REGEXP = "(^((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4}){1}|:))|(([0-9A-Fa-f]{1,4}:){6}((:[0-9A-Fa-f]{1,4}){1}|"
            + "((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})){3})|:))|"
            + "(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|"
            + "[0-1][0-9][0-9]|([0-9]){1,2})){3})|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|"
            + "([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})){3})|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|"
            + ":((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})){3})|:))|"
            + "(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|"
            + "[0-1][0-9][0-9]|([0-9]){1,2})){3})|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:((22[0-3]|2[0-1][0-9]|[0-1][0-9][0-9]|"
            + "([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})){3})|:))|(:((:[0-9A-Fa-f]{1,4}){1,7}|(:[fF]{4}){0,1}:((22[0-3]" +
            "|2[0-1][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})([.](25[0-5]|2[0-4][0-9]|[0-1][0-9][0-9]|([0-9]){1,2})){3})|:)))$)";
    Pattern IP6_PATTERN = Pattern.compile(IP6_REGEXP);

    /**
     * IP地址验证
     * @param ip
     * @return
     */
    static boolean isIP4(String ip) {
        if(StringUtil.isBlank(ip)){
            return false;
        }
        return IP4_PATTERN.matcher(ip).matches();
    }
    String IP4_REGEXP = "^(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)$";
    Pattern IP4_PATTERN = Pattern.compile(IP4_REGEXP);

    /**
     * IP地址验证
     * @param ip
     * @return
     */
    static boolean isIP(String ip) {
        if(StringUtil.isBlank(ip)){
            return false;
        }
        return ip.contains(":") ? isIP6(ip) : isIP4(ip);
    }
    String IP_MSG = "IP地址不正确";

    /**
     * 身份证号码验证
     * @param idcard
     * @return
     */
    static boolean isIdcard(String idcard) {
        if(null == idcard || idcard.length() != 18){
            return false;
        }
        if(!IDCARD_PATTERN.matcher(idcard).matches()){
            return false;
        }
        char[] chars = idcard.toCharArray();
        String sub = new String(chars, 0, 2);
        boolean flag = true;
        for(String c : cityCode){
            if(c.equals(sub)){
                flag = false;
                break;
            }
        }
        if (flag){
            return false;
        }
        sub = new String(chars, 6, 8);
        try {
            if((new SimpleDateFormat(IDCARD_DATE_FMT).parse(sub).getTime() + 24*3600) > System.currentTimeMillis()){
                return false;
            }
        } catch (ParseException e) {
            return false;
        }
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += (chars[i]&0x0f) * IDCARD_POWER[i];
        }
        return IDCARD_JY[sum%11] == chars[17];
    }
    String IDCARD_MSG = "身份证号码不正确";
    String IDCARD_DATE_FMT = "yyyyMMdd";
    String IDCARD_REGEXP = "^\\d{17}[\\d|x]|\\d{15}$";
    Pattern IDCARD_PATTERN = Pattern.compile(IDCARD_REGEXP);
    String[] cityCode = { "11", "12", "13", "14", "15", "21", "22", "23", "31", "32", "33", "34", "35", "36",
            "37", "41", "42", "43", "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63", "64", "65", "71", "81", "82", "91" };
    int[] IDCARD_POWER = { 7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2 };
    char[] IDCARD_JY = {'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'};

    /**
     * 银行卡校验
     * @param bankCard
     * @return
     */
    static boolean isBankCard(String bankCard) {
        if(StringUtil.isBlank(bankCard) || bankCard.length() < 15 || bankCard.length() > 19 || !bankCard.matches("\\d+")) {
            return false;
        }
        char[] chs = bankCard.substring(0, bankCard.length() - 1).toCharArray();
        int luhmSum = 0;
        for(int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
            int k = chs[i] - '0';
            if(j % 2 == 0) {
                k *= 2;
                k = k / 10 + k % 10;
            }
            luhmSum += k;
        }
        return bankCard.charAt(bankCard.length() - 1) == ((luhmSum % 10 == 0) ? '0' : (char)((10 - luhmSum % 10) + '0'));
    }
    String BANK_CARD_MSG = "银行卡号不正确";

    /**
     * 营业执照 统一社会信用代码（15位）
     * @param license
     * @return
     */
    static boolean isLicense15(String license) {
        if(StringUtil.isBlank(license) || license.length() != 15 || !license.matches("\\d+")) {
            return false;
        }
        char[] chars = license.substring(0,14).toCharArray();
        int ti = 0;
        int si = 0;
        int cj = 0;
        int pj = 10;
        for (int i=0; i<chars.length; i++) {
            ti = chars[i]&0x0f;
            pj = (cj % 11) == 0 ? 10 : (cj % 11);
            si = pj + ti;
            cj = (0 == si % 10 ? 10 : si % 10) * 2;
            if (i == chars.length-1) {
                pj = (cj % 11) == 0 ? 10 : (cj % 11);
                return (pj == 1 ? 1 : 11 - pj) == (license.charAt(license.length() - 1)&0x0f);
            }
        }
        return false;
    }

    /**
     * 营业执照 统一社会信用代码（18位）
     * @param license
     * @return
     */
    static boolean isLicense18(String license) {
        if(StringUtil.isBlank(license) || license.length() != 18 || !LICENSE18_PATTERN.matcher(license).matches()) {
            return false;
        }
        int[] ws = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
        String[] codes = new String[2];
        codes[0] = license.substring(0, license.length() - 1);
        codes[1] = license.substring(license.length() - 1, license.length());
        int sum = 0;
        for (int i = 0; i < 17; i++) {
            sum += LICENSE18_STR.indexOf(codes[0].charAt(i)) * ws[i];
        }
        int c18 = 31 - (sum % 31);
        if (c18 == 31) {
            c18 = 'Y';
        } else if (c18 == 30) {
            c18 = '0';
        }
        if (LICENSE18_STR.charAt(c18) != codes[1].charAt(0)) {
            return false;
        }
        return true;
    }
    String LICENSE18_STR = "0123456789ABCDEFGHJKLMNPQRTUWXY";
    String LICENSE18_REGEX = "^([0-9ABCDEFGHJKLMNPQRTUWXY]{2})(\\d{6})([0-9ABCDEFGHJKLMNPQRTUWXY]{10})$";
    Pattern LICENSE18_PATTERN = Pattern.compile(LICENSE18_REGEX);

    /**
     * 营业执照 统一社会信用代码
     * @param license
     * @return
     */
    static boolean isLicense(String license) {
        if(StringUtil.isBlank(license)){
            return false;
        }
        if(license.length() == 18){
            return isLicense18(license);
        }
        return isLicense15(license);
    }
    String LICENSE_MSG = "营业执照号不正确";

    /**
     *
     * @param url
     * @return
     */
    static boolean isUrl(String url) {
        if(StringUtil.isBlank(url)){
            return false;
        }
        return URL_PATTERN.matcher(url).matches();
    }
    String URL_REGEX = "^((https|http|ftp|rtsp|mms)?:\\/\\/)[^\\s]+";
    Pattern URL_PATTERN = Pattern.compile(URL_REGEX);
    String URL_MSG = "url不正确";

}
